"""
Case Type   : 资源池化
Case Name   : 系统函数query_node_reform_info函数字段及功能验证
Create At   : 2024.6
Owner       : haomeng
Description :
    1、备节点退出集群,cm_ctl stop -n 2
    2、查询集群reform相关统计信息
    3、备节点加入集群, cm_ctl start -n 2
    4、查询集群reform相关统计信息
    5、集群switchover, cm_ctl switchover -n 2 -D $PGDATA
    6、查询集群reform相关统计信息
    7、集群failover
    8、查询集群reform相关统计信息
    9、恢复环境为初始状态
Expect      :
    1、备节点退出集群成功
    2、查询reform统计信息成功，reform_type为Normal reform，节点动作action为kick off
    3、备节点加入集群成功
    4、查询reform统计信息成功，reform_type为Normal reform，节点动作action为join in
    5、集群主动进行switchover成功
    6、查询reform统计信息成功，待升主节点reform_type为switchover，异常节点动作action为stable,升主节点动作为stable
    7、集群发生failover成功
    8、查询reform统计信息成功，待升主节点reform_type为Fauilover，异常节点动作action为kick off,升主节点动作为stable
    9、恢复成功
"""

import os
import unittest
import time
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Common import Common
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import macro
from yat.test import Node


class SharedStorage(unittest.TestCase):

    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.sta_sh = [CommonSH('Standby1DbUser'), CommonSH('Standby2DbUser')]
        self.usernode = Node('PrimaryDbUser')
        self.constant = Constant()
        self.com = Common()

        self.log.info('------检查数据库状态是否正常------')
        status = self.pri_sh.exec_cm_ctl('query', '-Cv')
        self.assertIn("cluster_state   : Normal", status)

    def test_innerfunc(self):
        text = '-----step1:备节点退出集群; expect:退出成功-----'
        self.log.info(text)

        stop_dn = self.pri_sh.exec_cm_ctl('stop', '-n 2')
        self.log.info(stop_dn)
        self.assertIn(self.constant.cm_stop_node_success_msg, stop_dn,
                      'stop备节点失败')


        status = self.pri_sh.exec_cm_ctl('query', '-Cv')
        self.log.info(status)

        text = '-----step2:查询集群reform相关统计信息; expect:查询reform统计信息成功，' \
               'reform_type为Normal reform，节点动作action为kick off-----'
        self.log.info(text)

        reform_inner = 'select * from query_node_reform_info();'
        self.log.info(reform_inner)

        res1 = self.pri_sh.execut_db_sql(reform_inner)
        self.log.info(res1)
        self.assertIn('1', res1.splitlines()[3].split('|')[0], '节点信息异常')
        self.assertIn('kick off', res1.splitlines()[3].split('|')[-1], '节点信息异常')

        text = '-----step3:备节点加入集群; expect:加入成功-----'
        self.log.info(text)

        start_dn = self.pri_sh.exec_cm_ctl('start', '-n 2')
        self.log.info(start_dn)
        self.assertIn(self.constant.cm_start_node_success_msg, start_dn,
                      'start备节点失败')

        status = self.pri_sh.exec_cm_ctl('query', '-Cv')
        self.log.info(status)

        text = '-----step4:查询集群reform相关统计信息; expect:查询reform统计信息成功,' \
               'reform_type为Normal reform，节点动作action为join in'
        self.log.info(text)

        res2 = self.pri_sh.execut_db_sql(reform_inner)
        self.log.info(res2)
        self.assertIn('1', res2.splitlines()[3].split('|')[0], '节点信息异常')
        self.assertIn('join in', res2.splitlines()[3].split('|')[-1], '节点信息异常')

        text = '-----step5:集群主动发起switchover,使备1升主; expect:switchover操作成功-----'
        self.log.info(text)

        switch_dn = self.pri_sh.exec_cm_ctl('switchover', '-n 2',
                                            f'-D {macro.DB_INSTANCE_PATH}')
        self.log.info(switch_dn)
        self.assertIn(self.constant.cm_switchover_success_msg, switch_dn,
                      'switchover操作失败')
        status = self.pri_sh.exec_cm_ctl('query', '-Cv')
        self.log.info(status)

        text = '-----step6:查询集群reform相关统计信息; expect:查询reform统计信息成功,' \
               '待升主节点reform_type为switchover，异常节点动作为stable,升主节点动作为stable-----'
        self.log.info(text)

        res3 = self.sta_sh[0].execut_db_sql(reform_inner)
        self.log.info(res3)
        self.assertIn('1', res3.splitlines()[3].split('|')[0], '节点信息异常')
        self.assertIn('Switchover', res3.splitlines()[3].split('|')[1], '节点信息异常')
        self.assertIn('stable', res3.splitlines()[3].split('|')[-1], '节点信息异常')

        text = '-----step7:集群failover; expect:成功-----'
        self.log.info(text)

        self.log.info('-----恢复集群初始状态-----')
        recovery = self.pri_sh.exec_cm_ctl('switchover', '-a')
        self.log.info(recovery)
        self.assertIn(self.constant.cm_switchover_success_msg, recovery,
                      '恢复集群初始状态失败')

        for i in range(8):
            dn_pid = self.com.get_pid(self.usernode, 'bin/gaussdb')
            self.log.info(dn_pid)
            kill_dn = self.usernode.sh(f'kill -9 {dn_pid}').result()
            time.sleep(6)

        dn_pid2 = self.com.get_pid(self.usernode, 'bin/gaussdb')
        self.log.info(dn_pid2)
        self.assertEqual('', dn_pid2, 'dn进程存在')

        status = self.pri_sh.exec_cm_ctl('query', '-Cv')
        self.log.info(status)

        text = '-----step8:查询集群reform相关统计信息; expect:查询reform统计信息成功,' \
               '待升主节点reform_type为Failover，异常节点动作为kick off,升主节点动作为stable-----'
        self.log.info(text)

        self.log.info('-----获取当前主节点------')
        time.sleep(10)
        pri_node = self.pri_sh.get_primary_node()
        self.log.info(pri_node)

        res4 = self.sta_sh[0].execut_db_sql(reform_inner) if pri_node == '2' \
            else self.sta_sh[1].execut_db_sql(reform_inner)
        self.log.info(res4)

        self.assertIn('1', res4.splitlines()[3].split('|')[0], '节点信息异常')
        self.assertIn('kick off', res4.splitlines()[2].split('|')[-1], '节点信息异常')

    def tearDown(self):
        text = '-----step9:恢复集群初始状态; expect:恢复初始状态成功-----'
        self.log.info(text)

        start_dn = self.pri_sh.exec_cm_ctl('start')
        self.log.info(start_dn)

        recovery_dn = self.pri_sh.exec_cm_ctl('switchover', '-a')
        self.log.info(recovery_dn)
        self.assertIn(self.constant.cm_start_success_msg, start_dn,
                      '拉起集群失败')
        self.assertIn(self.constant.cm_switchover_success_msg, recovery_dn,
                      '恢复集群初始状态失败')
        self.log.info(f'-----{os.path.basename(__file__)} end-----')
